
//===============================================================================
// Original Author: CC Dharmani, Chennai (India) www.dharmanitech.com
// Must use little-endian and maximum 2 byte alignment in target architecture
//===============================================================================

typedef enum FAT_FILE_FLAGS_e
{
	FAT_FILE_GOOD = 0,
	FAT_FILE_ERR,
	FAT_FILE_EOF
} FAT_FILE_STATUS_t;

struct FAT_FILE_t
{
	unsigned long	start_cluster; // FAT Based cluster index number
	unsigned long	current_cluster; // FAT Based current buffered sector index
	unsigned long	cluster_index;
	unsigned	sector_index;
	unsigned long	byte_index;

	char		filename[12];	// 8.3 Fat Filename + null terminator
	unsigned long	size;
	unsigned char		buf[512];		// Sector buffer

	FAT_FILE_STATUS_t flags;

};

// Structure to access Master Boot Record for getting info about partioions
struct MBRinfo_Structure {
	unsigned char     nothing[446];			// ignore, placed here to fill the gap in the structure
	unsigned char     partitionData[64];	// partition records (16x4)
	unsigned short    signature;			// 0xaa55
};

// Structure to access info of the first partioion of the disk 
struct partitionInfo_Structure {
	unsigned char     status;				// 0x80 - active partition
	unsigned char     headStart;			// starting head
	unsigned short    cylSectStart;			// starting cylinder and sector
	unsigned char     type;					// partition type 
	unsigned char     headEnd;				// ending head of the partition
	unsigned short    cylSectEnd;			// ending cylinder and sector
	unsigned long     firstSector;			// total sectors between MBR & the first sector of the partition
	unsigned long     sectorsTotal;			// size of this partition in sectors
};

// Structure to access boot sector data (volume ID)
struct BS_Structure {
	unsigned char     jumpBoot[3];			// default: 0x009000EB
	unsigned char     OEMName[8];
	unsigned char     bytesPerSectorL;		// deafault: 512
	unsigned char     bytesPerSectorH;		
	unsigned char     sectorPerCluster;		// 1, 2, 4, 8, 16, 32, 64, 128
	unsigned short    reservedSectorCount;	// number of reserved sectors, usually 32
	unsigned char     numberofFATs;			// number of FAT, always 2
	unsigned char     rootEntryCountL;
	unsigned char     rootEntryCountH;
	unsigned char     totalSectors_F16L;	// must be 0 for FAT32
	unsigned char     totalSectors_F16H;	// must be 0 for FAT32
	unsigned char     mediaType;
	unsigned short    FATsize_F16;			// must be 0 for FAT32
	unsigned short    sectorsPerTrack;
	unsigned short    numberofHeads;
	unsigned long     hiddenSectors;
	unsigned long     totalSectors_F32;
	unsigned long     FATsize_F32;			// count of sectors occupied by one FAT
	unsigned short    extFlags;
	unsigned short    FSversion;			// 0x0000 (defines version 0.0)
	unsigned long     rootCluster;			// first cluster of root directory (=2)
	unsigned short    FSinfo;				// sector number of FSinfo structure (=1)
	unsigned short    BackupBootSector;
	unsigned char     reserved[12];
	unsigned char     driveNumber;
	unsigned char     reserved1;
	unsigned char     bootSignature;
	unsigned char     volumeID[4];
	unsigned char     volumeLabel[11];		// "NO NAME "
	unsigned char     fileSystemType[8];	// "FAT32"
	unsigned char     bootData[420];
	unsigned short    bootEndSignature;		// 0xaa55
};

// Structure to access FSinfo sector data
struct FSInfo_Structure {
	unsigned long     leadSignature;		// 0x41615252
	unsigned char     reserved1[480];
	unsigned long     structureSignature;	// 0x61417272
	unsigned long     freeClusterCount;		// initial: 0xffffffff
	unsigned long     nextFreeCluster;		// initial: 0xffffffff
	unsigned char     reserved2[12];
	unsigned long     trailSignature;		// 0xaa550000
};

// Structure to access Directory Entry in the FAT
struct dir_Structure {
	unsigned char     name[11];
	unsigned char     attrib;				// file attributes
	unsigned char     NTreserved;			// always 0
	unsigned char     timeTenth;			// tenths of seconds, set to 0 here
	unsigned short    createTime;			// time file was created
	unsigned short    createDate;			// date file was created
	unsigned short    lastAccessDate;
	unsigned short    firstClusterHI;		// higher word of the first cluster number
	unsigned short    writeTime;			// time of last write
	unsigned short    writeDate;			// date of last write
	unsigned short    firstClusterLO;		// lower word of the first cluster number
	unsigned long     fileSize;				// size of file in bytes
};

// Attribute definitions for file/directory
#define ATTR_READ_ONLY     0x01
#define ATTR_HIDDEN        0x02
#define ATTR_SYSTEM        0x04
#define ATTR_VOLUME_ID     0x08
#define ATTR_DIRECTORY     0x10
#define ATTR_ARCHIVE       0x20
#define ATTR_LONG_NAME     0x0f
#define DIR_ENTRY_SIZE     0x32
#define EMPTY              0x00
#define DELETED            0xe5
#define GET				0
#define SET				1
#define ADD				0
#define REMOVE			1
#define TOTAL_FREE		1
#define NEXT_FREE		2
#define GET_FILE		1
#define SET_FILE        2
#define ADD_FILE        3
#define DEL_FILE        4

// File creation date
#define FILE_YEAR		2011
#define FILE_MONTH		1
#define FILE_DAY		1
#define FILE_HOUR		12
#define FILE_MINUTE		0
#define FILE_SECOND		0

// FAT32 specific sizes
#define  BYTE_PER_SECTOR		 512	// Size of one sector in byte - almost a standard
#define  BYTE_PER_SECTOR_WIDTH	 9		// = number of 0's in BYTE_PER_SECTOR
#define  CLSA_PER_SECTOR		 128	// Number of cluster addresss per sector
#define  MAX_SEC_PER_CLS		 32		// Maximum number of sector per cluster - 16kB max cluster size per Microsoft standard

